import axios from 'axios';
import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig
} from 'axios';
import {
  ElMessageBox as MessageBox,
  ElNotification as Notification,
  ElMessage as Message
} from 'element-plus';
import NProgress from 'nprogress'; // 引入进度条
import 'nprogress/nprogress.css';
import {getToken} from "@/utils/auth.ts"; // 引入进度条样式

// 定义 API 响应格式
export interface ApiResponse<T = number | object | null | object[] | unknown> extends AxiosResponse<T> {
  code: number;
  message: string;
  data: T;
}


const errorCode: Record<string, string> = {
  'default': '系统未知错误，请反馈给管理员',
  '401': '用户没有权限（令牌、用户名、密码错误）',
  '403': '用户得到授权，但是访问是被禁止的。',
  '404': '访问资源不存在',
  '405': '请求方法未允许',
  '408': '请求超时',
  '500': '服务器错误，请检查服务器',
  '501': '服务未实现',
  '502': '网络错误',
  '503': '服务不可用',
  '504': '网络超时',
};

/**
 * 参数处理
 * @param params 参数
 */
function tansParams(params: Record<string, string>): string {
  let result = '';
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    const part = encodeURIComponent(propName) + "=";
    if (value !== null && value !== "" && typeof (value) !== "undefined") {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
            const paramsKey = propName + '[' + key + ']';
            const subPart = encodeURIComponent(paramsKey) + "=";
            result += subPart + encodeURIComponent(value[key]) + "&";
          }
        }
      } else {
        result += part + encodeURIComponent(value) + "&";
      }
    }
  }
  return result;
}

// 设置默认请求头
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';

console.log(import.meta.env)
export const apiPath: string = import.meta.env.VITE_API_BASE_URL;
// 创建 axios 实例
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,// axios中请求配置有baseURL选项，表示请求URL公共部分
  timeout: 10000,// 超时
});
NProgress.configure({
  showSpinner: false,
});
// request 拦截器
service.interceptors.request.use(
  (config: AxiosRequestConfig): InternalAxiosRequestConfig => {
    NProgress.start();
    // 是否需要设置 token
    const ignoreToken = (config.headers || {})['ignoreToken'];
    if (!ignoreToken) {
      // 使用 axios 提供的 headers 操作方法
      if (config.headers) {
        const token = getToken()
        if (token){
          config.headers['Authorization'] = 'Bearer ' + token; 
        }
      }
    }
    // get请求映射params参数
    if (config.method === 'get' && config.params) {
      let url = config.url + '?' + tansParams(config.params);
      url = url.slice(0, -1);
      config.params = {};
      config.url = url;
    }
    // 需要返回 InternalAxiosRequestConfig 类型
    return config as InternalAxiosRequestConfig;
  },
  (error: unknown) => {
    NProgress.done();
    console.log(error);
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (res: AxiosResponse<ApiResponse, unknown>): ApiResponse | Promise<AxiosResponse<ApiResponse, unknown>> => {
    NProgress.done();
    // 未设置状态码则默认成功状态 0也是200
    const code = res.data.code || 200;
    // 获取错误信息
    const msg = errorCode[code] || res.data.message || errorCode['default'];
    // 二进制数据则直接返回
    if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
      return res.data;
    }
    if (code === 401) {
      MessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', {
        confirmButtonText: '重新登录',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        location.href = '/';
      }).catch(() => {
      });
      return Promise.reject('无效的会话，或者会话已过期，请重新登录。');
    } else if (code === 500) {
      Message({message: res.data.message || msg, type: 'error'});
      return Promise.reject(new Error(msg));
    } else if (code === 601) {
      Message({message: msg, type: 'warning'});
      return Promise.reject('error');
    } else if (code !== 200) {
      Notification.error({title: msg});
      return Promise.reject(res.data.message || msg);
    } else {
      return res.data;
    }
  },
  (error) => {
    NProgress.done();
    console.log('err' + error);
    let {message} = error;
    if (message === "Network Error") {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    Message({message: message, type: 'error', duration: 5 * 1000});
    return Promise.reject(error);
  }
);

export default service;
